package com.uw.uwconfig.client.repository;

import com.alibaba.fastjson.TypeReference;
import com.uw.uwconfig.client.config.ConfigServerMeta;
import com.uw.uwconfig.client.contant.PropertyNameConstant;
import com.uw.uwconfig.client.util.HttpUtil;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class UwRepositoryImpl implements UwRepository {

    private final Environment environment;
    private final ApplicationContext applicationContext;

    Map<String, Map<String, Object>> configHolder = new HashMap<>();

    public UwRepositoryImpl(Environment environment, ApplicationContext applicationContext) {
        this.environment = environment;
        this.applicationContext = applicationContext;
    }

    @Override
    public Map<String, Object> getConfig(ConfigServerMeta meta) {
        Map<String, Object> result = ConfigCacheHolder.getConfig(meta.key());
        if (CollectionUtils.isEmpty(result)) {
            result = getConfigWithoutCache(meta);
            ConfigCacheHolder.putConfig(meta.key(), result);
        }
        return result;
    }

    @Override
    public Map<String, Object> getConfigWithoutCache(ConfigServerMeta meta) {
        List<Configs> configs = HttpUtil.httpGet(meta.listUrl("list"), new TypeReference<>() {
        });
        return configs.stream().collect(Collectors.toMap(Configs::getPkey, Configs::getPval, (t1, t2) -> t1));
    }

    @Override
    public Long version(ConfigServerMeta meta) {
        return HttpUtil.httpGet(meta.version("version"), new TypeReference<>() {
        });
    }

    @Override
    public void onChange(ChangeEvent changeEvent) {
        Map<String, Object> config = changeEvent.config();

        MapPropertySource mapPropertySource = new MapPropertySource(PropertyNameConstant.UW_PROPERTY_SOURCE, config);
        CompositePropertySource compositePropertySource = new CompositePropertySource(PropertyNameConstant.UW_PROPERTY_SOURCES);
        compositePropertySource.addPropertySource(mapPropertySource);

        ConfigurableEnvironment ENV = (ConfigurableEnvironment) environment;
        ENV.getPropertySources().replace(PropertyNameConstant.UW_PROPERTY_SOURCES, compositePropertySource);

        // 发送事件，触发更新ConfigurationProperties 和 @Value
        applicationContext.publishEvent(new EnvironmentChangeEvent(config.keySet()));
    }
}
